package vengadores;

import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;

/**
 *Es la clase que maneja los eventos específicos de la fase de Shooter del juego. En esta clase se manejan los disparos, la interacción del jugador con el juego, del heroe con el enemigo
 * y de los eventos que surjan de estas interacciones.
 * @author Felipe Donato Arrazola Gómez
 * @author Jorge de Jesús Tinoco Huesca
 * @author Arturo Ayala Tello
 */
public class AdminShooter extends LayerManager{
    /**
     * Es un objeto de tipo Heroe, que será el personaje dentro del juego de Shooter.
     */
    protected Heroe heroe;
    /**
     * Es la imagen de la mira del personaje.
     */
    protected Sprite mira;
    /**
     * Es un vector que contiene objetos tipo Enemigo, que aparecerán dentro del juego.
     */
    protected Vector enemigos;
    /**
     * Es la cantidad de enemigos que se deben derrotar para pasar la fase de shooter.
     */
    public static int MATAR_Y_PASAR;
    /**
     * Representan la posición de la mira.
     */
    protected int yMira, xMira;
    /**
     * Es la imagen que se despliega cuando el personaje recibe un impacto de parte los enemigos.
     */
    private Sprite herida;
    /**
     * Indica si el personaje está en el proceso de disparar.
     */
    protected boolean estaDisparando = false;

    private Juego juego; //juego al que pertenece el administrador
    private int enemigosDerrotados; //entero que guarda cuántos enemigos has eliminado
    private int balasActuales;//entero que guarda las balas actuales en el cartucho
    private int cartuchos;//entero que guarda los cartuchos del heroe
    private int sexo; //entero que guarda el género del heroe
    private int ANCHO, ALTO; //medidas de la pantalla
    private int balasCartucho;//balas que hay en el cartucho siguiente
    private Fondo fondo; //fondo del administrador
    private Sprite impacto;//Sprite que representa el impacto de una bala
    private Image bala;//Imagen de una bala
    private Image recargar; // letrero que se muestra cuando ya no hay balas en el cartucho
    private Image cartucho; // Imagen del cartucho
    private int[] secuenciaImpacto = {0,0,1,1,3,3,2}; //secuencia del impacto de la bala
    private static int ULTDISPARO; // entero que guarda la ultima posición de la secuencia de la bala
    private Random r; //objeto para crear números aleatorios
    private int nivel;// entero que guarda el nivel actual
    private int disparosMaximos; //entero que guarda el máximo de disparos que tiene el heroe
    private static int LIMITE_SHOOTER; // entero que almacena el tiempo del sprite del enemigo del shooter
    private int tipoEnemigo; // tipo de enemigos en el modo Shooter
    private boolean direccion=false; // false = izquierda true = derecha
    private int random; // entero que almacena el numero generado por el objeto Random
    /**
     * variable que guarda el puntaje obtenido durante este modo de Juego
     */
    protected int puntaje=0;
    /**
     * Variable que recupera si el jefe ha sido derrotado o no
     */
    protected boolean jefeDerrotado = false;
    private StringBuffer info;//para generar la info a desplegar
    private String infoDesplegada; //cuantos enemigos faltan
    private String infoCartuchos; //cuantos cartuchos tiene el heroe
    /**
     * Constructor de la clase en donde se crea el objeto que administra el juego en fase de shooter.
     * @param ancho Es un entero que indica el ancho de la pantalla.
     * @param alto Entero que indica el alto de la pantalla.
     * @param sexo Entero que representa el género del personaje escogido por el jugador.
     * @param nivel Es un entero que representa el nivel del juego.
     */
    public AdminShooter(Juego jgo, int ancho, int alto, int sexo, int nivel, int tipoEnemigo){
        this.sexo = sexo;
        this.nivel = nivel;
        this.ANCHO = ancho;
        this.ALTO = alto;
        juego = jgo;
        xMira = ANCHO/2;
        yMira = ALTO/2;
        r = new Random();
        ULTDISPARO = secuenciaImpacto.length-1;
        cartuchos = 4;
        balasCartucho = 10;
        balasActuales = 10;
        enemigosDerrotados = 0;
        disparosMaximos = 1;
        this.tipoEnemigo = tipoEnemigo;
        try{
            mira = new Sprite(Image.createImage("/Mira"+this.sexo+".png"));
            herida = new Sprite(Image.createImage("/Herida.png"));
            this.append(mira);
            this.append(herida);
            recargar = Image.createImage("/recarga.png");
            impacto = new Sprite(Image.createImage("/impacto.png"), 70, 60);
            impacto.setFrameSequence(secuenciaImpacto);
            this.append(impacto);
            impacto.setVisible(false);
            bala = Image.createImage("/Bala.png");
            cartucho = Image.createImage("/cartucho.png");
            switch (this.nivel){
                case 1:
                    fondo = new Fondo("/ShooterJuarez.png");
                    LIMITE_SHOOTER = 70;
                    MATAR_Y_PASAR = 20;
                    break;
                case 2:
                    fondo = new Fondo("/AcapulcoShooter.png");
                    MATAR_Y_PASAR = 10;
                    LIMITE_SHOOTER = 65;
                    break;
                case 3:
                    fondo = new Fondo("/MexicoShooter.png");
                    LIMITE_SHOOTER = 60;
                    MATAR_Y_PASAR = 5;
                    break;
                default:
                    break;
            }
            if(tipoEnemigo == Enemigo.SHOOTER){
                    enemigos = new Vector(nivel);
                    for(int i=0;i<nivel;i++){
                        enemigos.addElement(new Enemigo(Enemigo.SHOOTER, nivel));
                    }
                    int numeroEnemigos = enemigos.size();
                    for(int i=0;i<numeroEnemigos; i++){
                        Enemigo e = (Enemigo) enemigos.elementAt(i);
                        e.setPosition(r.nextInt(200), 35 + r.nextInt(130));
                        this.append(e);
                    }
            }else if(tipoEnemigo == Enemigo.JEFE) {
                    enemigos = new Vector(1);
                    Jefe jefe = new Jefe(nivel);
                    enemigos.addElement(jefe);
                    jefe.setPosition(r.nextInt(200), 35 + r.nextInt(120));
                    this.append(jefe);
                    LIMITE_SHOOTER = 50;
                    MATAR_Y_PASAR = nivel*10;
            }

            heroe = new Heroe(sexo);
            this.append(heroe);

        }catch(Exception e){
            e.printStackTrace();
        }
        heroe.setPosition(10, 230);
        herida.setVisible(false);
        info = new StringBuffer();
    }

    /**
     * Método para obtener la posición en X de la mira.
     * @return la posición en X de la mira
     */
    public int getxMira() {
        return xMira;
    }

    /**
     * Método para obtener la posición en Y de la mira.
     * @return la posición en Y de la mira
     */
    public int getyMira() {
        return yMira;
    }

    /**
     * Método para cambiar la posición en X de la mira.
     * @param xMira es la nueva posición en X que tendrá la imagen de la mira.
     */
    public void setxMira(int xMira) {
        if(xMira > 0 && xMira < ANCHO-mira.getWidth()){
            this.xMira = xMira;
        }
    }

    /**
     * Método para cambiar la posición en Y de la mira.
     * @param yMira es la nueva posición en Y que tendrá la imagen de la mira.
     */
    public void setyMira(int yMira) {
        if(yMira > 0 && yMira < ALTO-mira.getHeight())
            this.yMira = yMira;
    }
    /**
     * Método que regresa cuántos cartuchos le quedan al personaje
     * @return el numero de cartuchos restantes
     */
    public int getCartuchos(){
        return cartuchos;
    }

    /**
     * Método que forma las cadenas para desplegar en pantalla
     */
    public void formarInfo(){
        info.delete(0, info.length());
        if ((MATAR_Y_PASAR - enemigosDerrotados) == 1){
            info.append("Falta ").append((MATAR_Y_PASAR - enemigosDerrotados)).append(" enemigo");
        }else{
            info.append("Faltan ").append((MATAR_Y_PASAR - enemigosDerrotados)).append(" enemigos");
        }
        infoDesplegada = info.toString();
        info.delete(0, info.length());
        info.append("X").append(cartuchos);
        infoCartuchos = info.toString();
    }

    /**
     * Método que dibuja todos los elementos del administrador del shooter.
     * @param g es el Graphics donde se dibujarán los objetos del administrador del Shooter.
     */
    public void dibujar(Graphics g) {
        formarInfo();
        mira.paint(g);
        fondo.dibujar(g);
        impacto.paint(g);
        int contador = ANCHO-bala.getWidth();
        for(int i=0; i<balasActuales; i++){
            g.drawImage(bala, contador, ALTO, Graphics.LEFT|Graphics.BOTTOM);
            contador-=10;
        }
        g.drawImage(cartucho, ANCHO-(cartucho.getWidth()*2), ALTO-bala.getHeight(), Graphics.LEFT|Graphics.BOTTOM);
        g.setColor(0xFFFFFF);
        g.drawString(infoCartuchos, ANCHO, ALTO-bala.getHeight(), Graphics.RIGHT|Graphics.BOTTOM);
        if(!heroe.estaCubierto){
            mira.setPosition(xMira, yMira);
            mira.setVisible(true);
        }
        if(balasActuales==0 && cartuchos != 0){
            g.drawImage(recargar, recargar.getWidth(), ALTO, Graphics.LEFT|Graphics.BOTTOM);
        }
        paint(g, 0, 0);
        if(tipoEnemigo == Enemigo.SHOOTER){
            movimientoEnemigo();
            g.setColor(0xFFFFFF);
            g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
            g.drawString(infoDesplegada, 0, ALTO, Graphics.LEFT|Graphics.BOTTOM);
        }else{
            movimientoJefe();
            Jefe jefe = (Jefe)enemigos.elementAt(0);
            int vidaJefe = (((MATAR_Y_PASAR-jefe.vecesGolpeado)*100)/MATAR_Y_PASAR);
            if (vidaJefe <= 20){
                g.setColor(0xA60000);
            }else if(vidaJefe <= 50){
                g.setColor(0xFFF700);
            }else{
                g.setColor(0x53DF00);
            }
            g.fillRect(ANCHO-10, 60, 10, vidaJefe*2);
        }

    }
    /**
     * Método utilizado para que el heroe dispare.
     */
    public void disparar(){
        if(balasActuales>0){
            if(!estaDisparando){
            estaDisparando = true;
            impacto.setVisible(true);
            }
            impacto.setPosition(xMira-14, yMira-9);
            impacto.nextFrame();
            if(impacto.getFrame() == ULTDISPARO){
                estaDisparando = false;
                impacto.setVisible(false);
                balasActuales--;
            }
        }
    }

    /**
     * Método utilizado para que el heroe recargue las balas en el cartucho actual.
     */
    public void recargarBalas(){
        if(cartuchos>0 && balasActuales<10){
            balasCartucho = balasCartucho - (10-balasActuales);
            balasActuales = 10;
            if(balasCartucho <= 0){
                cartuchos--;
                balasCartucho = 10 + balasCartucho;

            }
        }
    }

    /**
     * Método que elimina las referencias de esta clase
     */
    public void terminar(){
        heroe = null;
        int numeroEnemigos = enemigos.size();
        for (int i = 0; i<numeroEnemigos; i++){
            Enemigo e = (Enemigo)enemigos.elementAt(i);
            e = null;
        }
        enemigos = null;
        fondo.terminar();
        fondo = null;
        mira = null;
        impacto = null;
        bala = null;
        recargar = null;
        r = null;
    }

    /**
     * Método que maneja cómo se mueven los enemigos dentro del Shooter.
     */
    public void movimientoEnemigo(){
        int numeroEnemigos = enemigos.size();
        for(int i=0; i<numeroEnemigos; i++){
            Enemigo enemigo = (Enemigo) enemigos.elementAt(i);
            movNormal(enemigo);
        }
    }

    /**
     * Método que se encarga de mover al Jefe en el área de la pantalla
     */

    public void movimientoJefe(){
        Jefe jefe = (Jefe) enemigos.elementAt(0);
        int x = jefe.getX();
        int y = jefe.getY();
        int altoJefe = jefe.getHeight();
        int anchoJefe = jefe.getWidth();
        if(jefe.vecesGolpeado>=MATAR_Y_PASAR || jefe.estaMuriendo){
            jefe.morir();
            if(jefe.getFrame() == Jefe.ULTMUERTO){
                puntaje+=2000;
                jefeDerrotado = true;
            }
        }else if((estaDisparando && ((mira.getX() - x < anchoJefe && mira.getX() - x > -anchoJefe)
                && (mira.getY() - y < altoJefe && mira.getY() - y > -altoJefe))) || jefe.haSidoGolpeado) {
            jefe.golpeado();
            if(jefe.getFrame() == 0){
                jefe.vecesGolpeado++;
            }
            if(jefe.getFrame()== Jefe.ULTGOLPEADO){
                jefe.contadorShooter = 0;
                jefe.setPosition(r.nextInt(150), 35 + r.nextInt(100));
            }
        }else if(jefe.estaAtacando){
            jefeAtacar(jefe,random);
            jefeHacerDaño(jefe);
        }else if(jefe.contadorShooter == LIMITE_SHOOTER/4){
            random = r.nextInt(10);
            jefeAtacar(jefe, random);
        }else{
            jefe.estaAtacando = false;
            jefe.caminar(direccion);
        }
        if(jefe.contadorShooter == LIMITE_SHOOTER){
            jefe.contadorShooter = -1;
        }
        if(x<0 || x>(ANCHO-anchoJefe)){
            if(direccion){
                jefe.setPosition(x-5,y);
            }else{
                jefe.setPosition(5, y);
            }
            direccion = !direccion;
        }
        jefe.contadorShooter++;
        jefe.nextFrame();
    }

    //Método que se encarga del ataque del jefe
    private void jefeAtacar(Jefe jefe, int ataque){
        if(jefe.estaDisparando){
            jefe.disparar();
            return;
        }else if(jefe.estaBurlando){
            jefe.burlar();
            return;
        }else if(jefe.haciendoEspecial){
            jefe.especial();
            return;
        }

        if(ataque >= 0 && ataque <6){
            jefe.disparar();
        }else if(ataque >=6 && ataque <8){
            jefe.burlar();
        }else if(ataque >=8){
            jefe.especial();
        }

    }

    //Método que maneja el daño hacia el jefe
    private void jefeHacerDaño(Jefe jefe){
        if(!heroe.estaCubierto && jefe.estaDisparando){
            if((jefe.getContenidoFrame(jefe.getFrame())==Jefe.FRAME_DANIO) && !heroe.haSidoGolpeado){
                if (juego.getMidlet().deseaVibracion())
                    Display.getDisplay(juego.getMidlet()).vibrate(500);
                Heroe.SANGRE--;
                herida.setVisible(true);
                heroe.haSidoGolpeado = true;
            }else{
                heroe.haSidoGolpeado = false;
                herida.setVisible(false);
            }
        }else if(!heroe.estaCubierto && jefe.haciendoEspecial){
            if(jefe.getContenidoFrame(jefe.getFrame())>=Jefe.FRAME_DANIO_ESP){
                if (juego.getMidlet().deseaVibracion())
                    Display.getDisplay(juego.getMidlet()).vibrate(500);
                Heroe.SANGRE=0;
                herida.setVisible(true);
            }
        }else{
                herida.setVisible(false);
        }
    }

    //Método que se encarga del movimiento del enemigo
    private void movNormal(Enemigo enemigo) {
        if (enemigo.vecesGolpeado == disparosMaximos) {
            enemigosDerrotados++;
            puntaje+=75;
            enemigo.desaparecerShooter();
            enemigo.contadorShooter = 0;
            enemigo.vecesGolpeado = 0;
        } else if (enemigo.contadorShooter == 0 || enemigo.estaApareciendo) {
            enemigo.aparecerShooter();
        } else if (enemigo.contadorShooter == LIMITE_SHOOTER / 2 || enemigo.estaDisparando) {
            enemigo.disparar();
            if (!heroe.estaCubierto) {
                herida.setVisible(true);
                if (enemigo.getFrame() == Enemigo.ULTDISPARO) {
                    if(juego.getMidlet().deseaVibracion())
                        Display.getDisplay(juego.getMidlet()).vibrate(500);
                    Heroe.SANGRE--;
                }
            }
            if (enemigo.getFrame() == Enemigo.ULTDISPARO) {
                herida.setVisible(false);
            }
        } else if (enemigo.contadorShooter == LIMITE_SHOOTER || enemigo.estaDesapareciendo) {
            enemigo.desaparecerShooter();
            enemigo.contadorShooter = 0;
        } else {
            enemigo.setFrameSequence(null);
            enemigo.setFrame(4);
            if (estaDisparando && ((mira.getX() - enemigo.getX() < 20 && mira.getX() - enemigo.getX() > -20)
                    && (mira.getY() - enemigo.getY() < 20 && mira.getY() - enemigo.getY() > -20))) {
                enemigo.setFrame(7);
                enemigo.vecesGolpeado++;
            }
        }
        enemigo.contadorShooter++;
        enemigo.nextFrame();
    }

    /**
     * Método para obtener los enemigos que han sido derrotados.
     * @return la cantidad de enemigos que han sido derrotados en el Shooter por el heroe.
     */
    public int getEnemigosDerrotados() {
        return enemigosDerrotados;
    }

}